
package org.puremvc.as3.multicore.demos.flex.hellopipes.shell.view
{
	import org.puremvc.as3.multicore.demos.flex.hellopipes.common.IPipeAwareModule;
	import org.puremvc.as3.multicore.demos.flex.hellopipes.common.PipeAwareModuleConstants;
	import org.puremvc.as3.multicore.demos.flex.hellopipes.shell.ApplicationFacade;
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.utilities.pipes.interfaces.IPipeMessage;
	import org.puremvc.as3.multicore.utilities.pipes.messages.Message;
	import org.puremvc.as3.multicore.utilities.pipes.plumbing.Junction;
	import org.puremvc.as3.multicore.utilities.pipes.plumbing.JunctionMediator;
	import org.puremvc.as3.multicore.utilities.pipes.plumbing.Pipe;
	import org.puremvc.as3.multicore.utilities.pipes.plumbing.TeeMerge;
	import org.puremvc.as3.multicore.utilities.pipes.plumbing.TeeSplit;
	
	public class ShellJunctionMediator extends JunctionMediator
	{

		//
		// vars

		//
		// const	
		public static const NAME:String = 'ShellJunctionMediator';
		//
		// instances
					
		
		public function ShellJunctionMediator( )
		{
			super( NAME, new Junction() );
		}

		/**
		 * Called when the Mediator is registered.
		 */
		override public function onRegister():void
		{

		}
		
		/**
		 * ShellJunction related Notification list.
		 */
		override public function listNotificationInterests():Array
		{
 			var interests:Array = super.listNotificationInterests();			
			interests.push( ApplicationFacade.MODULE_ADDED );
			interests.push( ApplicationFacade.SEND_MESSAGE_TO_MODULE );				
			return interests; 
		}

		/**
		 * Handle ShellJunction related Notifications
		 * 
		 * @param 	note	Notification sended by an actor
		 */
		override public function handleNotification( note:INotification ):void
		{
			switch( note.getName() )
			{							
				case ApplicationFacade.MODULE_ADDED:
					connectModule( note.getBody() as IPipeAwareModule );
					break;
				case ApplicationFacade.SEND_MESSAGE_TO_MODULE:
					junction.sendMessage( PipeAwareModuleConstants.SHELL_TO_MODULE_PIPE,
											new Message( PipeAwareModuleConstants.SHELL_TO_MODULE_MESSAGE,
															null,
															note.getBody() ));											
					break;					
				
				// Let super handle the rest (ACCEPT_OUTPUT_PIPE, ACCEPT_INPUT_PIPE, SEND_TO_LOG)								
				default:
					super.handleNotification(note);
					
			}			

		}
			
		
		/**
		 * Handle incoming pipe messages for the ShellJunction.
		 * 
		 * @param message 	Message typed as IPipeMessage
		 */
		override public function handlePipeMessage( message:IPipeMessage ):void
		{
			switch ( Message(message).getType() )
			{
				case PipeAwareModuleConstants.MODULE_TO_SHELL_MESSAGE:
					sendNotification( ApplicationFacade.MESSAGE_FROM_MODULE_RECEIVED, 
										Message(message).getBody() );
					break;

			}
		}
			
		/**
		 * Connect the module using pipes and its TeeMerge and TeeSplit
		 * 
		 * @param module	Module typed as IPipeAwareModule
		 */
		public function connectModule( module:IPipeAwareModule ):void
		{
			//
			// Register SHELL_TO_MODULE_PIPE from the shell to all modules 
			junction.registerPipe( PipeAwareModuleConstants.SHELL_TO_MODULE_PIPE,  
									Junction.OUTPUT, 
									new TeeSplit() );
			//
			// Register MODULE_TO_SHELL_PIPE to the shell from all modules 
			junction.registerPipe( PipeAwareModuleConstants.MODULE_TO_SHELL_PIPE,  
									Junction.INPUT, 
									new TeeMerge() );
			//
			// add a pipe listener for messages sended by module						
			junction.addPipeListener( PipeAwareModuleConstants.MODULE_TO_SHELL_PIPE, 
										this, 
										handlePipeMessage );
			// module -> shell
			var moduleToShell: Pipe = new Pipe();
			module.acceptOutputPipe( PipeAwareModuleConstants.MODULE_TO_SHELL_PIPE, moduleToShell );
			
			var shellInFitting: TeeMerge = junction.retrievePipe( PipeAwareModuleConstants.MODULE_TO_SHELL_PIPE ) as TeeMerge;
			shellInFitting.connectInput( moduleToShell );
			
			// shell -> module
			var shellToModule: Pipe = new Pipe();
			module.acceptInputPipe( PipeAwareModuleConstants.SHELL_TO_MODULE_PIPE, shellToModule );
			
			var shellOutFitting: TeeSplit = junction.retrievePipe( PipeAwareModuleConstants.SHELL_TO_MODULE_PIPE ) as TeeSplit;
			shellOutFitting.connect( shellToModule );
			
				
		}					
		/**
		 * Disconnect the pipes from shell to module 
		 */
		public function disconnectModule():void
		{
			//
			// remove both pipes (shell -> module && module -> shell ), 
			// we don't need these after unloading the module		
			junction.removePipe( PipeAwareModuleConstants.MODULE_TO_SHELL_PIPE );
			junction.removePipe( PipeAwareModuleConstants.SHELL_TO_MODULE_PIPE );	 

		}	
				
	}
}